import os
import re
import shutil
import argparse
from pathlib import Path

def replace_in_file(file_path, old, new):
    """替换文件内容中的字符串"""
    with open(file_path, "r", encoding="utf-8") as f:
        content = f.read()
    new_content = content.replace(old, new)
    if new_content != content:
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(new_content)
        return True
    return False

def replace_groupid_in_pom(file_path, old_group, new_group):
    """替换 pom.xml 中的 groupId"""
    with open(file_path, "r", encoding="utf-8") as f:
        content = f.read()
    new_content = re.sub(
        rf"<groupId>\s*{re.escape(old_group)}\s*</groupId>",
        f"<groupId>{new_group}</groupId>",
        content
    )
    if new_content != content:
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(new_content)
        print(f"Updated groupId in {file_path}")

def move_package_dirs(root_dir, old_group, new_group):
    """修改包目录结构 org/dromara -> com/example"""
    old_parts = old_group.split(".")
    new_parts = new_group.split(".")

    for path in Path(root_dir).rglob("src"):
        # 只处理符合 maven 目录结构的
        if path.name == "src":
            for src_type in ["main", "test"]:
                java_path = path / src_type / "java"
                if java_path.exists():
                    old_path = java_path.joinpath(*old_parts)
                    new_path = java_path.joinpath(*new_parts)

                    if old_path.exists():
                        new_path.parent.mkdir(parents=True, exist_ok=True)

                        if new_path.exists():
                            # 合并到已存在的目录
                            for sub in old_path.rglob("*"):
                                rel = sub.relative_to(old_path)
                                target = new_path / rel
                                if sub.is_dir():
                                    target.mkdir(parents=True, exist_ok=True)
                                else:
                                    shutil.move(str(sub), str(target))
                            shutil.rmtree(old_path)
                            print(f"Merged {old_path} → {new_path}")
                        else:
                            shutil.move(str(old_path), str(new_path))
                            print(f"Moved {old_path} → {new_path}")

                        # 清理空的上级目录（例如 org）
                        parent = old_path.parent
                        while parent != java_path and parent.exists() and not any(parent.iterdir()):
                            print(f"Removing empty dir {parent}")
                            parent.rmdir()
                            parent = parent.parent

def process_project(root_dir, old_group, new_group):
    """遍历项目，修改 pom.xml、java 文件、配置文件"""
    for dirpath, _, filenames in os.walk(root_dir):
        for filename in filenames:
            filepath = os.path.join(dirpath, filename)

            # 修改 pom.xml
            if filename == "pom.xml":
                replace_groupid_in_pom(filepath, old_group, new_group)

            # 修改 Java 源码
            elif filename.endswith(".java"):
                if replace_in_file(filepath, old_group, new_group):
                    print(f"Updated package/import in {filepath}")

            # 修改配置文件 (yml/properties/xml/imports)
            elif filename.endswith((".yml", ".yaml", ".properties", ".xml", ".vm")) \
                 or filename == "org.springframework.boot.autoconfigure.AutoConfiguration.imports":
                if replace_in_file(filepath, old_group, new_group):
                    print(f"Updated config in {filepath}")

    # 修改源码目录结构
    move_package_dirs(root_dir, old_group, new_group)

def main():
    parser = argparse.ArgumentParser(
        description="批量修改 Maven 多模块项目的 groupId 和包名"
    )
    parser.add_argument("--old", required=True, help="旧的 groupId，例如 org.dromara")
    parser.add_argument("--new", required=True, help="新的 groupId，例如 com.example")
    parser.add_argument("--path", required=True, help="Maven 项目根目录路径")
    args = parser.parse_args()

    process_project(args.path, args.old, args.new)

if __name__ == "__main__":
    main()
